package com.bfly.mall.system.service.impl;

import com.bfly.core.base.service.BaseServiceImpl;
import com.bfly.core.context.event.SysConfigReloadEvent;
import com.bfly.core.enums.SysError;
import com.bfly.core.exception.ServiceResponseException;
import com.bfly.mall.system.dao.SysConfigMapper;
import com.bfly.mall.system.dto.*;
import com.bfly.mall.system.entity.*;
import com.bfly.mall.system.enums.SysConfigType;
import com.bfly.mall.system.service.ISysConfigService;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Field;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 长沙商脉科技有限公司
 * @date 2020/9/19 12:29
 */
@Service
@Transactional(propagation = Propagation.SUPPORTS)
public class SysConfigServiceImpl extends BaseServiceImpl<SysConfig, Integer> implements ISysConfigService {

    @Autowired
    private SysConfigMapper sysConfigMapper;
    @Autowired
    private ApplicationContext context;

    private void setConfigObject(Object obj, SysConfigType configType) {
        List<SysConfig> list = getConfig(configType.getId());
        final Field[] fields = obj.getClass().getDeclaredFields();
        list.forEach(sysConfig -> {
            String key = sysConfig.getName();
            if (StringUtils.isNotBlank(key)) {
                for (Field field : fields) {
                    if (field.getName().equals(key)) {
                        try {
                            field.setAccessible(true);
                            field.set(obj, ConvertUtils.convert(sysConfig.getData(), field.getType()));
                        } catch (IllegalAccessException e) {
                            throw new ServiceResponseException(SysError.PARAM_ERROR, "不存在该配置项!");
                        }
                    }
                }
            }
        });
    }

    @Override
    public WXMiniProConfigDTO getWxMiniProConfig() {
        WXMiniProConfigDTO config = new WXMiniProConfigDTO();
        setConfigObject(config, SysConfigType.WX_MINIPRO);
        return config;
    }

    @Override
    public WXMPConfigDTO getWxMpConfig() {
        WXMPConfigDTO config = new WXMPConfigDTO();
        setConfigObject(config, SysConfigType.WX_MP);
        return config;
    }

    @Override
    public WXPayConfigDTO getWxPayConfig() {
        WXPayConfigDTO config = new WXPayConfigDTO();
        setConfigObject(config, SysConfigType.WX_PAY);
        return config;
    }

    @Override
    public OrderConfigDTO getOrderConfig() {
        OrderConfigDTO config = new OrderConfigDTO();
        setConfigObject(config, SysConfigType.ORDER);
        return config;
    }

    @Override
    public WaterMarkDTO getWaterMarkConfig() {
        WaterMarkDTO config = new WaterMarkDTO();
        setConfigObject(config, SysConfigType.WATER_MARK);
        return config;
    }

    @Override
    public SystemConfigDTO getSystemConfig() {
        SystemConfigDTO config = new SystemConfigDTO();
        setConfigObject(config, SysConfigType.SYSTEM);
        return config;
    }

    @Override
    public List<SysConfig> getConfig(int type) {
        Map<String, Object> param = new HashMap<>(1);
        param.put("type", type);
        return super.getList(param);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void merge(int type, List<SysConfig> configs) {
        // 先清空已有的配置信息然后再保存 然后刷新内存配置信息
        sysConfigMapper.clearConfig(type);

        for (SysConfig config : configs) {
            config.setCreateDate(new Date());
            config.setUpdateDate(config.getCreateDate());
            super.save(config);
        }
        // 重新加载缓存
        context.publishEvent(new SysConfigReloadEvent(context));
    }
}
